/*
 * @Description:
 * @Version: @1.0.0
 * @Autor: YJY
 * @Date: 2021-07-20 15:25:38
 * @LastEditors: YJY
 * @LastEditTime: 2021-07-20 16:04:27
 */
import { foreachV } from './utils'
let Vue
export class Store { // 容器
  constructor (options) {
    console.log(options)
    // 实现 getters 因为是方法所以要将 {属性：fn} 转换为 {属性: 值} 实现缓存机制
    const computed = {}
    const getters = options.getters
    this.getters = {}
    foreachV(getters, (key, fn) => {
      computed[key] = () => {
        return fn(this.state)
      }
      Object.defineProperty(this.getters, key, {
        get: () => {
          return this.vm[key]
        }
      })
    })
    // 先实现 state 功能 使用监听实现响应式
    this.vm = new Vue({
      data: {
        state: options.state
      },
      computed
    })
    const mutations = options.mutations
    this.mutations = {}
    foreachV(mutations, (key, fn) => {
      this.mutations[key] = (data) => {
        return fn(this.state, data)
      }
    })
    const actions = options.actions
    this.actions = {}
    foreachV(actions, (key, fn) => {
      this.actions[key] = (data) => {
        return fn(this, data)
      }
    })
  }

  // 实现 mutations
  commit = (name, data) => {
    this.mutations[name](data)
  }

  // actions
  dispatch = (name, data) => {
    this.actions[name](data)
  }

  get state () {
    return this.vm.state
  }
}

// 先为每一所用的实例添加一个 $store
export const install = function (_Vue) { // 开发插件 _Vue引入Vue 1.可以使用Vue中的方法 2.和Vue版本同步
  Vue = _Vue
  Vue.mixin({
    beforeCreate () { // 这里体现了Vue的渲染关系 父子关系
      const options = this.$options
      if (options.store) { // 这里为根实例 因为在main.js中挂载了store
        this.$store = options.store
      } else { // 不是根实例
        this.$store = this.$parent && this.$parent.$store
      }
    }
  })
}
